﻿//
// IRobotController.cs
//
// Authors:
//    Claus Jørgensen <10229@iha.dk>
//    Jens Bloch Christensen <09584@iha.dk>
//    Jonas Daugaard Møller <08814@iha.dk>
//
using System;
using System.Diagnostics.Contracts;

namespace RSD.Robot
{
    /// <summary>
    /// Defines the methods required for using the Intelitek USBC-Controller.
    /// </summary>
    [ContractClass(typeof(Contracts.IRobotControllerContract))]
    public interface IRobotController : IRobotControllerAsync, IDisposable
    {
        #region Events

        /// <summary>
        /// Occurs when the USBC Controller finished initializing.
        /// </summary>
        event EventHandler<InitializationCompletedEventArgs> InitializationCompleted;

        /// <summary>
        /// Occurs when the homing status changes.
        /// </summary>
        event EventHandler<HomingStatusEventArgs> HomingStatusChanged;

        /// <summary>
        /// Occurs when the USBC Controller recieves digital input.
        /// </summary>
        event EventHandler<IOEventArgs> DigitalInputReceived;

        /// <summary>
        /// Occurs when the USBC Controller recieves digital output.
        /// </summary>
        event EventHandler<IOEventArgs> DigitalOutputReceived;

        /// <summary>
        /// Occurs when the joint status changes.
        /// </summary>
        event EventHandler<JointStatusEventArgs> JointStatusChanged;

        /// <summary>
        /// Occurs when the control status changes.
        /// </summary>
        event EventHandler<ControlStatusEventArgs> ControlStatusChanged;

        /// <summary>
        /// Occurs when a motion is started.
        /// </summary>
        event EventHandler<MotionEventArgs> MotionStarted;

        /// <summary>
        /// Occurs when a motion have ended.
        /// </summary>
        event EventHandler<MotionEventArgs> MotionEnded;

        /// <summary>
        /// Occurs when a unspecified action have started.
        /// </summary>
        event EventHandler ActionStarted;

        /// <summary>
        /// Occurs when a unspecified action have completed.
        /// </summary>
        event EventHandler ActionCompleted;

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the folder which contains the robot configuration files.
        /// </summary>
        string ParameterFolder
        {
            get;
            set;
        }

        /// <summary>
        /// Gets the robot version number.
        /// </summary>
        uint Version
        {
            get;
        }

        /// <summary>
        /// Gets a value indicating whether the emergency button has activated or not.
        /// </summary>
        bool IsEmergency
        {
            get;
        }

        /// <summary>
        /// Gets a value indicating whether the robot is in teaching mode or not.
        /// </summary>
        bool IsInTeachingMode
        {
            get;
        }

        /// <summary>
        /// Gets a value indicating whether the robot is online.
        /// </summary>
        bool IsOnline
        {
            get;
        }

        /// <summary>
        /// Gets the configuration for the connected robot.
        /// </summary>
        USBCConfiguration Configuration
        {
            get;
        }

        /// <summary>
        /// Gets the width between the grippers fingers.
        /// </summary>
        Tuple<short, short> Jaw
        {
            get;
        }

        #endregion

        #region Configuration

        /// <summary>
        /// Finds the USB device connected to the robot and initializes the connection 
        /// between the robot and the computer, using the default <see cref="SystemType"/>.
        /// </summary>
        /// <param name="mode">Initialization mode.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool Initialization(InitializationMode mode);

        /// <summary>
        /// Finds the USB device connected to the robot and initializes the connection 
        /// between the robot and the computer.
        /// </summary>
        /// <param name="mode">Initialization mode.</param>
        /// <param name="systemType">System type.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool Initialization(InitializationMode mode, SystemType systemType);

        /// <summary>
        /// Closes the connection to the USBC Controller. 
        /// </summary>
        void Close();

        #endregion

        #region Input/Output

        /// <summary>
        /// Monitors the digital input.
        /// </summary>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool MonitorDigitalInput();

        /// <summary>
        /// Monitors the digital output.
        /// </summary>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool MonitorDigitalOutput();

        /// <summary>
        /// Gets the digital input.
        /// </summary>
        /// <returns>the digital input.</returns>
        uint GetDigitalInput();

        /// <summary>
        /// Gets the digital output.
        /// </summary>
        /// <returns>the digital output.</returns>
        uint GetDigitalOutput();

        #endregion

        #region Movement

        /// <summary>
        /// Monitors the robots movement.
        /// </summary>
        void MonitorMotion();

        /// <summary>
        /// Sets the time future movement should take, for the given axis.
        /// </summary>
        /// <param name="axis">Axis to move.</param>
        /// <param name="time">Movement time.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool SetTime(Axis axis, TimeSpan time);

        /// <summary>
        /// Sets the speed future movement should take, for the given axis.
        /// </summary>
        /// <remarks>
        /// A <paramref name="speed"/> of 0 will cause the movement to stop.
        /// </remarks>
        /// <param name="axis">Axis to move.</param>
        /// <param name="speed">Movement speed (0-10).</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool SetSpeed(Axis axis, int speed);

        /// <summary>
        /// Moves the robot by joints.
        /// </summary>
        /// <param name="vector">Vector to move to.</param>
        /// <returns>
        /// <c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.
        /// </returns>
        bool MoveJoint(Vector vector);

        /// <summary>
        /// Moves the robot by joints.
        /// </summary>
        /// <param name="vectorA">First vector to move to.</param>
        /// <param name="vectorB">Second vector to move to.</param>
        /// <returns>
        /// <c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.
        /// </returns>
        bool MoveJoint(Vector vectorA, Vector vectorB);

        /// <summary>
        /// Moves the robot in a linear path.
        /// </summary>
        /// <param name="vector">Vector to move to.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool MoveLinear(Vector vector);

        /// <summary>
        /// Moves the robot in a linear path.
        /// </summary>
        /// <param name="vectorA">First vector to move to.</param>
        /// <param name="vectorB">Second vector to move to.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool MoveLinear(Vector vectorA, Vector vectorB);

        /// <summary>
        /// Moves the conveyor belt.
        /// </summary>
        /// <param name="velocity">Speed/direction of the conveyor belt.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool MoveConveyorBelt(int velocity);

        /// <summary>
        /// Waits for conveyor belt to send input.
        /// </summary>
        void WaitForConveyorBelt();

        /// <summary>
        /// Moves to a position.
        /// </summary>
        /// <param name="position">Position.</param>
        /// <param name="pointType">Point type.</param>
        void MoveToPosition(Position position, PointType pointType);

        /// <summary>
        /// Opens the gripper.
        /// </summary>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool OpenGripper();

        /// <summary>
        /// Closes the gripper.
        /// </summary>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool CloseGripper();

        /// <summary>
        /// Stops all movement on the given axix.
        /// </summary>
        /// <param name="axis">Axis to move.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool StopMovement(Axis axis);

        /// <summary>
        /// Sets the default velocity of the given axis.
        /// </summary>
        /// <param name="axis">Axis to move.</param>
        /// <param name="velocity">Velocity in percent.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool SetVelocity(Axis axis, short velocity);

        /// <summary>
        /// Turns control on or off for the given axis.
        /// </summary>
        /// <param name="axis">Axis to move.</param>
        /// <param name="isOn">true to turn on, false to turn off.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool SetControl(Axis axis, bool isOn);

        /// <summary>
        /// Monitors the control status.
        /// </summary>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool MonitorControlStatus();

        /// <summary>
        /// Monitors the homing process.
        /// </summary>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool MonitorHomingStatus();

        /// <summary>
        /// Homes the robot.
        /// </summary>
        /// <param name="axis">Axis to move.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool Home(Axis axis);

        /// <summary>
        /// Sets the home position to the current position.
        /// </summary>
        /// <param name="axis">Axis to move.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool SetHome(Axis axis);

        /// <summary>
        /// Monitors the values for each joint on the robot.
        /// </summary>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool MonitorJointStatus();        

        #endregion

        #region Positioning

        /// <summary>
        /// Loads points into the robots memory from a file.
        /// </summary>
        /// <param name="fileName">The file to open.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool LoadPointsFromFile(string fileName);

        /// <summary>
        /// Defines a vector in the robots memory.
        /// </summary>
        /// <param name="axis">Axis to move.</param>
        /// <param name="vectorName">Name of the vector.</param>
        /// <returns>a vector with the given vectorname; otherwise, null.</returns>
        Vector DefineVector(Axis axis, string vectorName);

        /// <summary>
        /// Renames a vector in the robots memory.
        /// </summary>
        /// <param name="oldName">Old vector name.</param>
        /// <param name="newName">New vector name.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool RenameVector(string oldName, string newName);

        /// <summary>
        /// Deletes a vector in the robots memory.
        /// </summary>
        /// <remarks>
        /// If the vectors PointNumber property is set to -1 then all vectors are deleted.
        /// </remarks>
        /// <param name="vector">Vector to delete.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool DeleteVector(Vector vector);

        /// <summary>
        /// Deletes a vector point in the robots memory.
        /// </summary>
        /// <param name="vector">Vector to delete a point from.</param>
        /// <param name="point">Point to remove from the given vector.</param>
        /// <returns>
        /// <c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.
        /// </returns>
        bool DeleteVector(Vector vector, short point);

        /// <summary>
        /// Saves the current position as a point in memory.
        /// </summary>
        /// <param name="vector">Vector to save the position to.</param>
        /// <param name="pointType">Location point type.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool SaveCurrentLocation(Vector vector, PointType pointType);

        /// <summary>
        /// Teaches a robot the location of a named vector.
        /// </summary>
        /// <param name="vector">Vector to teach.</param>
        /// <param name="position">XYZ position to associate the vector with.</param>
        /// <param name="pointType">Location point type.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        bool Teach(Vector vector, Position position, PointType pointType);

        /// <summary>
        /// Gets the point information for a given vector and point-number.
        /// </summary>
        /// <param name="vector">Vector to get point information for.</param>
        /// <param name="pointType">Location point type.</param>
        /// <returns>point information for the given location.</returns>
        Position GetPointInfo(Vector vector, PointType pointType);

        /// <summary>
        /// Sets the joints.
        /// </summary>
        /// <param name="vector">The vector.</param>
        /// <param name="position">The position.</param>
        /// <param name="pointType">Type of the point.</param>
        /// <returns></returns>
        bool SetJoints(Vector vector, Position position, PointType pointType);

        /// <summary>
        /// Gets the current position of the robot.
        /// </summary>
        /// <returns>the robots current position.</returns>
        Position GetCurrentPosition();

        #endregion

        #region Action Queue

        /// <summary>
        /// Enqueues any RobotController action.
        /// </summary>
        /// <param name="item">Action delegate.</param>
        void EnqueueAction(Action<IRobotController> item);

        /// <summary>
        /// Triggers the ActionCompleted event.
        /// </summary>
        void TriggerActionCompleted();

        /// <summary>
        /// Executes the action queue.
        /// </summary>
        void RunActionQueue();
        
        #endregion
    }
}
